﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;

namespace Eazy
{
    public static class LazyBuilder
    {
        public static LazyBuilder<T> Create<T>()
        {
            return new LazyBuilder<T>();
        }

        public static LazyBuilder<T> Create<T>(Expression<Func<T>> expr)
        {
            throw new NotImplementedException();
        }
    }

    public class LazyBuilder<T>
    {
        private static LazyProxy<T> s_lazyProxy = new LazyProxy<T>();
        private static Func<T> s_defaultCreator = null;

        static LazyBuilder()
        {
            if (s_lazyProxy.HasDefaultConstructor)
            {
                var lambdaExpr = Expression.Lambda<Func<T>>(Expression.New(s_lazyProxy.ProxyType));
                s_defaultCreator = lambdaExpr.Compile();
            }
        }

        public T Instance { get; private set; }

        public LazyBuilder()
        {
            if (s_defaultCreator == null)
            {
                string message = String.Format("No default constructor defined for type {0}.", typeof(T));
                throw new InvalidOperationException(message);
            }

            this.Instance = s_defaultCreator();
        }

        public void Setup<TProperty>(Expression<Func<T, TProperty>> expr, Func<TProperty> loader)
        {
            var property = (expr.Body as MemberExpression).Member as PropertyInfo;
            s_lazyProxy.SetLazyLoader(property, this.Instance, loader);
        }
    }
}
